package com.xunwulian.dubbo.service;

import com.xunwulian.base.entity.CardInfoEntity;
import com.xunwulian.base.entity.SmsGprsBalanceEntity;
import com.xunwulian.base.entity.User;
import com.xunwulian.base.util.ExcelUtil;
import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Component
public class CardFileServer {

    private static final Logger logger = LoggerFactory.getLogger(CardFileServer.class);

    // 核心池大小
    private static final int CORE_POOL_SIZE = 10;

    // 最大线程数
    private static final int MAX_POOL_SIZE = 20;

    // 空闲线
    //
    // 程最大存活时间，单位分钟
    private static final long KEEP_ALIVE_TIME = 60;

    // 任务队列大小
    private static final int QUEUE_SIZE = 100;

    private static final int PER_THREAD = 1000;

    // 卡工具
    private ExcelUtil excelUtil = new ExcelUtil();

    @Autowired
    private InnerCardInfoService innerCardInfoService;

    @Autowired
    private InnerGprsSmsService innerGprsSmsService;

    /**
     * 某个线程失败，无法整体rollback
     *
     * @param file
     */
    public void process2db(String file, String appId, User user) {
        List<CardInfoEntity> infos = readFile(file);

        logger.error(String.format("start processing file : [%s]", file));

        for (int i = 0; i < infos.size(); i++) {
            CardInfoEntity info = infos.get(i);

            innerCardInfoService.addMsisdn(info.getMsisdn(), appId, user);
            logger.info("处理完成，info.getMsisdn()：" + info.getMsisdn());
        }
        logger.info(String.format("process over file:[%s]", file));
    }

    private List<CardInfoEntity> readFile(String path) {
        List<CardInfoEntity> cies = new ArrayList<>();

        Workbook workbook = excelUtil.loadExcel(path);
        if (workbook == null) {
            logger.error("workbook is null");
        } else {
            cies = excelUtil.parseCardInfoExcel(workbook);
        }

        logger.info(String.format("CardFile's size = [%d]", cies.size()));
        return cies;
    }


    /**
     * 某个线程失败，无法整体rollback
     *
     * @param file
     */
    public void parseGprsSms2db(String file) {
        List<SmsGprsBalanceEntity> infos = readGprsSmsFile(file);

        logger.info(String.format("start processing file : [%s]", file));
        // 线程执行器
        ThreadPoolExecutor tpec = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE,
                KEEP_ALIVE_TIME, TimeUnit.MINUTES, new ArrayBlockingQueue<>(QUEUE_SIZE));

        for (int i = 0; i < Math.ceil(infos.size() / PER_THREAD); i++) {
            logger.info(String.format("thread: [%d], start:[%d], end:[%d]", i + 1, i * PER_THREAD, (i + 1) * PER_THREAD));
            tpec.execute(new GprsSmsFileTask(innerGprsSmsService, infos, i * PER_THREAD, (i + 1) * PER_THREAD));
        }

        logger.info(String.format("process over file:[%s]", file));
    }


    private List<SmsGprsBalanceEntity> readGprsSmsFile(String path) {
        Workbook workbook = excelUtil.loadExcel(path);
        List<SmsGprsBalanceEntity> cies = excelUtil.parseGprsSmsExcel(workbook);

        logger.info(String.format("GprsSmsExcel's size = [%d]", cies.size()));

        return cies;
    }
}
